/*
 * z80.cpp
 *
 *  Created on: Jan 4, 2012
 *      Author: douglas
 */



#include "z80.hpp"


//#define call(op) (this->op)()

#include "z80_addressingModes.cpp"
#include "z80_opcodes.cpp"

//This method fetch the next opcode to be executed. It read the PC and check for 16 bits opcodes.
//The opcode read is stored in the "opcode" variable of this class.
void z80::z80_fetch(){

#ifdef Z80_TEST
	OpTCycles = 0;
	OpMCycles = 0;
#endif

	opcode = fetchPC(4);

	//Some instructions has 16bits opcode, so the following "if" check this stuff.
	//You can see in the opcode table construction that z80 has 8bits and 16bits opcodes.
	//Some instructions are 4 or 5 bytes long, having part of the opcode in byte 4, but
	//with only the first 2 bytes we can differenciate all instructions.
	if ((opcode == 0xCB) || (opcode == 0xDD) || (opcode == 0xED) || (opcode == 0xFD))
	{
		opcode <<= 8;
		opcode |= fetchPC(4);
	}
}

u8 z80::readPC(int cycles)
{
	return read8(regs.pc, 0);
}

u8 z80::fetchPC(int cycles)
{
	return read8(regs.pc++, 0);
}

void z80::z80_step()
{
#ifdef Z80_TEST
	cout << "Instruction: 0x" << hex << opcode << " : M Cycles = " << (int) OpMCycles << ", T Cycles = " << (int) OpTCycles << endl;
#endif
	z80_fetch(); //the class variable "opcode" will contain the opcode to be executed.
	//After fetching the opcode to be executed, we call run the instruction.
	(this->*op[opcode])(); //TODO: create a define for this (call).
}



inline u8 z80::z80_condition(u8 condId)
{
	switch (condId)
	{
	case _cNZ: return !regs.Flags.z;
	case _cZ:  return regs.Flags.z;
	case _cNC: return !regs.Flags.c;
	case _cC:  return regs.Flags.c;
	case _cPO: return !regs.Flags.pv;
	case _cPE: return regs.Flags.pv;
	case _cP:  return !regs.Flags.s;
	case _cM:  return regs.Flags.s;
	}
	return true;
}


void z80::z80_reset(){

	regs.pc = 0;
	regs.sp = 0;
	regs.IX = 0;
	regs.IY = 0;
	regs.s  = 0;
	regs.ss = 0;

	for (int i=0; i<8 ; i++)
	{
		*regs.r[i] = 0;
		regs.rs[i] = 0;
	}
}


void z80::setFlags(u16 tmp_A)
{

}


//this table is contructed following the exact order of Zack's book.
//The instructions not present in the book are inserted at the bottom of the method (see the comments).
//The instructions are separated in blocks.
//In most of cases each line of a block represent a different addressing mode, and in some cases a different pair register.
void z80::opcodeTable()
{
	for (int i=0; i<0x10000; i++) op[i] = &z80::op_illegal;


/*ADC A,r          */ op[0x8F]=op[0x88]=op[0x89]=op[0x8A]=op[0x8B]=op[0x8C]=op[0x8D]               = &z80::implicitAddressing8<&z80::op_adc_8bits>;         //
/*ADC A,n          */ op[0xCE]                                                                     = &z80::immediateAddressing<&z80::op_adc_8bits>;         ///
/*ADC A,(HL)	   */ op[0x8E]                                                                     = &z80::indirectAddressingRead<_HL, &z80::op_adc_8bits>;     ///// ADC
/*ADC A,(IX+d)     */ op[0xDD8E]                                                                   = &z80::indexedAddressing<_IX, &z80::op_adc_8bits>;      ////
/*ADC A,(IY+d)     */ op[0xFD8E]                                                                   = &z80::indexedAddressing<_IY, &z80::op_adc_8bits>;      ///
/*ADC HL,ss        */ op[0xED4A]=op[0xED5A]=op[0xED6A]=op[0xED7A]                                  = &z80::implicitAddressing16<_HL, &z80::op_adc_16bits>;       //

/*ADD A,(HL)       */ op[0x86]                                                                     = &z80::indirectAddressingRead<_HL, &z80::op_add_8bits>;     //
/*ADD A,(IX+d)     */ op[0xDD86]                                                                   = &z80::indexedAddressing<_IX, &z80::op_add_8bits>;      ///
/*ADD A,(IY+d)     */ op[0xFD86]                                                                   = &z80::indexedAddressing<_IY, &z80::op_add_8bits>;      ////
/*ADD A,n          */ op[0xC6]                                                                     = &z80::immediateAddressing<&z80::op_add_8bits>;         /////
/*ADD A,r          */ op[0x87]=op[0x80]=op[0x81]=op[0x82]=op[0x83]=op[0x84]=op[0x85]               = &z80::implicitAddressing8<&z80::op_add_8bits>;         ///// ADD
/*ADD HL,ss        */ op[0x09]=op[0x19]=op[0x29]=op[0x39]                                          = &z80::implicitAddressing16<_HL, &z80::op_add_16bits<_HL> >;  ////
/*ADD IX,rr        */ op[0xDD09]=op[0xDD19]=op[0xDD29]=op[0xDD39]                                  = &z80::implicitAddressing16<_IX, &z80::op_add_16bits<_IX> >;  ///
/*ADD IY,rr        */ op[0xFD09]=op[0xFD19]=op[0xFD29]=op[0xFD39]                                  = &z80::implicitAddressing16<_IY, &z80::op_add_16bits<_IY> >;  //

/*AND A,r          */ op[0xA7]=op[0xA0]=op[0xA1]=op[0xA2]=op[0xA3]=op[0xA4]=op[0xA5]               = &z80::implicitAddressing8<&z80::op_and_8bits>;         //
/*AND A,n          */ op[0xE6]                                                                     = &z80::immediateAddressing<&z80::op_and_8bits>;         ///
/*AND A,(HL)       */ op[0xA6]                                                                     = &z80::indirectAddressingRead<_HL, &z80::op_and_8bits>;     ///// AND
/*AND A,(IX+d)	   */ op[0xDDA6]                                                                   = &z80::indexedAddressing<_IX, &z80::op_and_8bits>;      ////
/*AND A,(IY+d)	   */ op[0xFDA6]                                                                   = &z80::indexedAddressing<_IY, &z80::op_and_8bits>;      ///

/*BIT b,(HL)	   */ op[0xCB46]=op[0xCB4E]=op[0xCB56]=op[0xCB5E]=op[0xCB66]                       = &z80::indirectAddressingRead<_HL, &z80::op_bit>;           //
/*BIT b,(HL) cont. */ op[0xCB6E]=op[0xCB76]=op[0xCB7E]                                             = &z80::indirectAddressingRead<_HL, &z80::op_bit>;           ///
/*BIT b,r          */ op[0xCB47]=op[0xCB40]=op[0xCB41]=op[0xCB42]=op[0xCB43]=op[0xCB44]            = &z80::implicitAddressing8<&z80::op_bit>;          ////
/*BIT b,r    cont. */ op[0xCB45]=op[0xCB4F]=op[0xCB48]=op[0xCB49]=op[0xCB4A]=op[0xCB4B]            = &z80::implicitAddressing8<&z80::op_bit>;          /////
/*BIT b,r    cont. */ op[0xCB4C]=op[0xCB4D]=op[0xCB57]=op[0xCB50]=op[0xCB51]=op[0xCB52]            = &z80::implicitAddressing8<&z80::op_bit>;          /////
/*BIT b,r    cont. */ op[0xCB53]=op[0xCB54]=op[0xCB55]=op[0xCB5F]=op[0xCB58]=op[0xCB59]            = &z80::implicitAddressing8<&z80::op_bit>;          ///// BIT
/*BIT b,r    cont. */ op[0xCB5A]=op[0xCB5B]=op[0xCB5C]=op[0xCB5D]=op[0xCB67]=op[0xCB60]            = &z80::implicitAddressing8<&z80::op_bit>;          /////
/*BIT b,r    cont. */ op[0xCB61]=op[0xCB62]=op[0xCB63]=op[0xCB64]=op[0xCB65]=op[0xCB6F]            = &z80::implicitAddressing8<&z80::op_bit>;          /////
/*BIT b,r    cont. */ op[0xCB68]=op[0xCB69]=op[0xCB6A]=op[0xCB6B]=op[0xCB6C]=op[0xCB6D]            = &z80::implicitAddressing8<&z80::op_bit>;          /////
/*BIT b,r    cont. */ op[0xCB77]=op[0xCB70]=op[0xCB71]=op[0xCB72]=op[0xCB73]=op[0xCB74]            = &z80::implicitAddressing8<&z80::op_bit>;          ////
/*BIT b,r    cont. */ op[0xCB75]=op[0xCB7F]=op[0xCB78]=op[0xCB79]=op[0xCB7A]=op[0xCB7B]            = &z80::implicitAddressing8<&z80::op_bit>;          ///
/*BIT b,r    cont. */ op[0xCB7C]=op[0xCB7D]                                                        = &z80::implicitAddressing8<&z80::op_bit>;          //

/*CALL cc,pq       */ op[0xC4]=op[0xCC]=op[0xD4]=op[0xDC]=op[0xE4]=op[0xEC]                        = &z80::immediateAddressing16<&z80::op_call<true> >;     ///// CALL
/*CALL cc,pq cont. */ op[0xCD]                                                                     = &z80::immediateAddressing16<&z80::op_call<false> >;    ///

/*CCF              */ op[0x3F]                                                                     = &z80::op_ccf;                                          ///// CCF

/*CP s             */ op[0xBF]=op[0xB8]=op[0xB9]=op[0xBA]=op[0x8B]=op[0x8C]=op[0x8D]               = &z80::implicitAddressing8<&z80::op_cp>;                ///
/*CP s             */ op[0xFE]                                                                     = &z80::immediateAddressing<&z80::op_cp>;                ////
/*CP s             */ op[0xBE]                                                                     = &z80::indirectAddressingRead<_HL, &z80::op_cp>;            ///// CP
/*CP s             */ op[0xDDBE]                                                                   = &z80::indexedAddressing<_IX, &z80::op_cp>;             ////
/*CP s             */ op[0xFDBE]                                                                   = &z80::indexedAddressing<_IY, &z80::op_cp>;             ///

/*CPD              */ op[0xEDA9]                                                                   = &z80::indirectAddressingRead<_HL, &z80::op_cpd>;           ///// CPD

/*CPDR             */ op[0xEDB9]                                                                   = &z80::indirectAddressingRead<_HL, &z80::op_cpdr>;          ///// CPDR

/*CPI              */ op[0xEDA1]                                                                   = &z80::indirectAddressingRead<_HL, &z80::op_cpi>;           ///// CPI

/*CPDR             */ op[0xEDB1]                                                                   = &z80::indirectAddressingRead<_HL, &z80::op_cpir>;          ///// CPIR

/*CPL              */ op[0x2F]                                                                     = &z80::op_cpl;                                          ///// CPL

/*CPL              */ op[0x27]                                                                     = &z80::op_daa;                                          ///// DAA

/*DEC m            */ op[0x3D]=op[0x05]=op[0x0D]=op[0x15]=op[0x1D]=op[0x25]=op[0x2D]               = &z80::implicitAddressing8<&z80::op_dec_8bits>;         ////
/*DEC m            */ op[0x35]                                                                     = &z80::indirectAddressingRead<_HL, &z80::op_dec_8bits>;     ///// DEC
/*DEC m            */ op[0xDD35]                                                                   = &z80::indexedAddressing<_IX, &z80::op_dec_8bits>;      ////
/*DEC m            */ op[0xFD35]                                                                   = &z80::indexedAddressing<_IY, &z80::op_dec_8bits>;      ///
/*DEC rr           */ op[0x0B]                                                                     = &z80::op_dec_16bits<_BC>;                              ///
/*DEC rr           */ op[0x1B]                                                                     = &z80::op_dec_16bits<_DE>;                              ///
/*DEC rr           */ op[0x2B]                                                                     = &z80::op_dec_16bits<_HL>;                              ///
/*DEC rr           */ op[0x3B]                                                                     = &z80::op_dec_16bits<_SP>;                              ///
/*DEC rr           */ op[0xDD2B]                                                                   = &z80::op_dec_16bits<_IX>;                              ///
/*DEC rr           */ op[0xFD2B]                                                                   = &z80::op_dec_16bits<_IY>;                              ///

/*DI               */ op[0xF3]                                                                     = &z80::op_di;                                           ///// DI

/*DJNZ e           */ op[0x10]                                                                     = &z80::immediateAddressing<&z80::op_djnz>;              ///// DJNZ

/*EI               */ op[0xFB]                                                                     = &z80::op_ei;                                           ///// EI

/*JP cc,pq         */ op[0xC2]=op[0xCA]=op[0xD2]=op[0xDA]=op[0xE2]=op[0xEA]=op[0xF2]               = &z80::immediateAddressing16<&z80::op_jp<true> >;       /////
/*JP cc,pq cont.   */ op[0xFA]                                                                     = &z80::immediateAddressing16<&z80::op_jp<true> >;       ///// JP
/*JP pq            */ op[0xC3]                                                                     = &z80::immediateAddressing16<&z80::op_jp<false> >;      ///// JP
/*JP (HL)          */ op[0xE9]                                                                     = &z80::implicitAddressing16<_HL, &z80::op_jp<false> >;  ////
/*JP (IX)          */ op[0xDDE9]                                                                   = &z80::implicitAddressing16<_IX, &z80::op_jp<false> >;  ////
/*JP (IY)          */ op[0xFDE9]                                                                   = &z80::implicitAddressing16<_IY, &z80::op_jp<false> >;  ////
/*JR cc,e          */ op[0x20]=op[0x28]=op[0x30]=op[0x38]                                          = &z80::relativeAddressing<&z80::op_jr<true> >;          ////
/*JR e             */ op[0x18]                                                                     = &z80::relativeAddressing<&z80::op_jr<false> >;         ////

/*LD dd,(nn)       */ op[0xED4B]=op[0xED5B]=op[0xED6B]=op[0xED7B]                                  = &z80::directAddressing16<&z80::op_load_to_pair_auto<true> >;         ////
/*LD dd,nn         */ op[0x01]=op[0x11]=op[0x21]=op[0x31]                                          = &z80::immediateAddressing16<&z80::op_load_to_pair_auto<false> >;         ////
/*LD r,n           */ op[0x3E]=op[0x06]=op[0x0E]=op[0x16]=op[0x1E]=op[0x26]=op[0x2E]               = &z80::immediateAddressing<&z80::op_load_to_reg_auto<false> >;         ////
/*LD r,r'          */ op[0x7F]=op[0x78]=op[0x79]=op[0x7A]=op[0x7B]=op[0x7C]=op[0x7D]               = &z80::implicitAddressing8<&z80::op_load_to_reg_auto<false> >;         ////
/*LD r,r' cont.    */ op[0x47]=op[0x40]=op[0x41]=op[0x42]=op[0x43]=op[0x44]=op[0x45]               = &z80::implicitAddressing8<&z80::op_load_to_reg_auto<false> >;         ////
/*LD r,r' cont.    */ op[0x4F]=op[0x48]=op[0x49]=op[0x4A]=op[0x4B]=op[0x4C]=op[0x4D]               = &z80::implicitAddressing8<&z80::op_load_to_reg_auto<false> >;         ////
/*LD r,r' cont.    */ op[0x57]=op[0x50]=op[0x51]=op[0x52]=op[0x53]=op[0x54]=op[0x55]               = &z80::implicitAddressing8<&z80::op_load_to_reg_auto<false> >;         ////
/*LD r,r' cont.    */ op[0x5F]=op[0x58]=op[0x59]=op[0x5A]=op[0x5B]=op[0x5C]=op[0x5D]               = &z80::implicitAddressing8<&z80::op_load_to_reg_auto<false> >;         ////
/*LD r,r' cont.    */ op[0x67]=op[0x60]=op[0x61]=op[0x62]=op[0x63]=op[0x64]=op[0x65]               = &z80::implicitAddressing8<&z80::op_load_to_reg_auto<false> >;         ////
/*LD r,r' cont.    */ op[0x6F]=op[0x68]=op[0x69]=op[0x6A]=op[0x6B]=op[0x6C]=op[0x6D]               = &z80::implicitAddressing8<&z80::op_load_to_reg_auto<false> >;         ////
/*LD (BC),A        */ op[0x02]                                                                     = &z80::indirectAddressingWrite<_BC, &z80::op_load_reg_to_mem_manual<_A> >;        ////
/*LD (DE),A        */ op[0x12]                                                                     = &z80::indirectAddressingWrite<_DE, &z80::op_load_reg_to_mem_manual<_A> >;        ////
/*LD (HL),n        */ op[0x36]                                                                     = &z80::immediateAddressing<&z80::indirectAddressingWrite<_HL, &z80::op_load_imm_to_mem> >;         ////
/*LD (HL),r        */ op[0x77]=op[0x70]=op[0x71]=op[0x72]=op[0x73]=op[0x74]=op[0x75]               = &z80::indirectAddressingWrite<_HL, &z80::op_load_reg_to_mem_auto>;         ////
/*LD r,(IX+d)      */ op[0xDD7E]=op[0xDD46]=op[0xDD4E]=op[0xDD56]=op[0xDD5E]=op[0xDD66]=op[0xDD6E] = &z80::indexedAddressing<_IX, &z80::op_load_to_reg_auto<false> >; //false because indexedAddressing alreasy reads from memory
/*LD r,(IY+d)      */ op[0xFD7E]=op[0xFD46]=op[0xFD4E]=op[0xFD56]=op[0xFD5E]=op[0xFD66]=op[0xFD6E] = &z80::indexedAddressing<_IY, &z80::op_load_to_reg_auto<false> >; //false because indexedAddressing alreasy reads from memory
/*LD (IX+d),n      */ op[0xDD36]                                                                   = &z80::indexedAddressingWrite<_IX, &z80::immediateAddressing<&z80::op_load_imm_to_mem> >;
/*LD (IY+d),n      */ op[0xFD36]                                                                   = &z80::indexedAddressingWrite<_IY, &z80::immediateAddressing<&z80::op_load_imm_to_mem> >;
/*LD (IX+d),r      */ op[0xDD77]=op[0xDD70]=op[0xDD71]=op[0xDD72]=op[0xDD73]=op[0xDD74]=op[0xDD75] = &z80::indexedAddressingWrite<_IX, &z80::op_load_reg_to_mem_auto>;
/*LD (IY+d),r      */ op[0xFD77]=op[0xFD70]=op[0xFD71]=op[0xFD72]=op[0xFD73]=op[0xFD74]=op[0xFD75] = &z80::indexedAddressingWrite<_IY, &z80::op_load_reg_to_mem_auto>;
/*LD A,(nn)        */ op[0x3A]                                                                     = &z80::directAddressing16<&z80::op_load_to_reg_manual<_A, true> >;         ////
/*LD (nn),A        */ op[0x32]                                                                     = &z80::directAddressing16<&z80::op_load_reg_to_mem_manual<_A> >;         ////
/*LD (nn),dd       */ op[0xED43]=op[0xED53]=op[0xED63]=op[0xED73]                                  = &z80::directAddressing16<&z80::op_load_pair_to_mem_auto>;         ////
/*LD (nn),HL       */ op[0x22]                                                                     = &z80::directAddressing16<&z80::op_load_pair_to_mem_manual<_HL> >;         ////
/*LD (nn),IX       */ op[0xDD22]                                                                   = &z80::directAddressing16<&z80::op_load_pair_to_mem_manual<_IX> >;         ////
/*LD (nn),IY       */ op[0xFD22]                                                                   = &z80::directAddressing16<&z80::op_load_pair_to_mem_manual<_IY> >;         ////
/*LD A,(BC)        */ op[0x0A]                                                                     = &z80::indirectAddressingRead<_BC, &z80::op_load_to_reg_manual<_A, false> >;        ////
/*LD A,(DE)        */ op[0x1A]                                                                     = &z80::indirectAddressingRead<_DE, &z80::op_load_to_reg_manual<_A, false> >;        ////
//TODO: Create a separate method for this special registers, so we can calculate the flags and eliminate the implicitaddressingmanual.
/*LD A,I           */ op[0xED57]                                                                   = &z80::implicitAddressing8_manual<_I, &z80::op_load_to_reg_manual<_A, false> >;         ////
/*LD I,A           */ op[0xED47]                                                                   = &z80::implicitAddressing8_manual<_A, &z80::op_load_to_reg_manual<_I, false> >;         ////
/*LD A,R           */ op[0xED5F]                                                                   = &z80::implicitAddressing8_manual<_R, &z80::op_load_to_reg_manual<_A, false> >;         ////
/*LD HL,(nn)       */ op[0x2A]                                                                     = &z80::directAddressing16<&z80::op_load_to_pair_manual<_HL, true> >;         ////
/*LD IX,nn         */ op[0xDD21]                                                                   = &z80::immediateAddressing16<&z80::op_load_to_pair_manual<_IX, false> >;         ////
/*LD IX,(nn)       */ op[0xDD2A]                                                                   = &z80::directAddressing16<&z80::op_load_to_pair_manual<_IX, true> >;         ////
/*LD IX,nn         */ op[0xFD21]                                                                   = &z80::immediateAddressing16<&z80::op_load_to_pair_manual<_IY, false> >;         ////
/*LD IX,(nn)       */ op[0xFD2A]                                                                   = &z80::directAddressing16<&z80::op_load_to_pair_manual<_IY, true> >;         ////
/*LD R,A           */ op[0xED4F]                                                                   = &z80::implicitAddressing8_manual<_A, &z80::op_load_to_reg_manual<_R, false> >;         ////
/*LD SP,HL         */ op[0xF9]                                                                     = &z80::implicitAddressing16<_HL, &z80::op_load_to_pair_manual<_SP, false> >;  ////
/*LD SP,IX         */ op[0xDDF9]                                                                   = &z80::implicitAddressing16<_IX, &z80::op_load_to_pair_manual<_SP, false> >;  ////
/*LD SP,IY         */ op[0xFDF9]                                                                   = &z80::implicitAddressing16<_IY, &z80::op_load_to_pair_manual<_SP, false> >;  ////
/*LD r,(HL)        */ op[0x7E]=op[0x46]=op[0x4E]=op[0x56]=op[0x5E]=op[0x66]=op[0x6E]               = &z80::indirectAddressingWrite<_HL, &z80::op_load_to_reg_auto<true> >;         ////


/*LDD              */ op[0xEDA8]                                                                   = &z80::indirectAddressingWrite<_HL, &z80::op_ldd >;        ////
/*LDDR             */ op[0xEDB8]                                                                   = &z80::indirectAddressingWrite<_HL, &z80::op_lddr >;        ////
/*LDI              */ op[0xEDA0]                                                                   = &z80::indirectAddressingWrite<_HL, &z80::op_ldi >;        ////
/*LDIR             */ op[0xEDB0]                                                                   = &z80::indirectAddressingWrite<_HL, &z80::op_ldir >;        ////

/*LDIR             */ op[0xEDB0]                                                                   = &z80::indirectAddressingWrite<_HL, &z80::op_ldir >;        ////


/*NEG              */ op[0xED44]                                                                   = &z80::op_neg;                                           ///// EI


/*NEG              */ op[0x0]                                                                      = &z80::op_nop;                                           ///// EI


/*OR  A,r          */ op[0xB7]=op[0xB0]=op[0xB1]=op[0xB2]=op[0xB3]=op[0xB4]=op[0xB5]               = &z80::implicitAddressing8<&z80::op_or_8bits>;         //
/*OR  A,n          */ op[0xF6]                                                                     = &z80::immediateAddressing<&z80::op_or_8bits>;         ///
/*OR  A,(HL)       */ op[0xB6]                                                                     = &z80::indirectAddressingRead<_HL, &z80::op_or_8bits>;     ///// AND
/*OR  A,(IX+d)	   */ op[0xDDB6]                                                                   = &z80::indexedAddressing<_IX, &z80::op_or_8bits>;      ////
/*OR  A,(IY+d)	   */ op[0xFDB6]                                                                   = &z80::indexedAddressing<_IY, &z80::op_or_8bits>;      ///


/*OTDR             */ op[0xEDBB]                                                                   = &z80::externalAddressing16<_HL, &z80::op_otdr >;        ////
/*OTIR             */ op[0xEDB3]                                                                   = &z80::externalAddressing16<_HL, &z80::op_otir >;        ////
/*OUT (C), r       */ op[0xED79]=op[0xED41]=op[0xED49]=op[0xED51]=op[0xED59]=op[0xED61]=op[0xED69] = &z80::externalAddressing8<&z80::op_out>;         //
/*OUT (N), A       */ op[0xD3]                                                                     = &z80::immediateAddressing<&z80::op_out_imm>;         //
/*OUTD             */ op[0xEDAB]                                                                   = &z80::externalAddressing16<_HL, &z80::op_outd >;         //
/*OUTI             */ op[0xEDA3]                                                                   = &z80::externalAddressing16<_HL, &z80::op_outi >;         //


/*POP qq           */ op[0xC1]=op[0xD1]=op[0xE1]                                                   = &z80::indirectAddressingWrite<_SP, &z80::op_pop_auto>;         //
/*POP qq           */ op[0xF1]                                                                     = &z80::indirectAddressingWrite<_SP, &z80::op_pop_manual<_AF> >;         //
/*POP IX           */ op[0xDDE1]                                                                   = &z80::indirectAddressingWrite<_SP, &z80::op_pop_manual<_IX> >;         //
/*POP IY           */ op[0xFDE1]                                                                   = &z80::indirectAddressingWrite<_SP, &z80::op_pop_manual<_IY> >;         //


/*PUSH qq          */ op[0xC5]=op[0xD5]=op[0xE5]                                                   = &z80::indirectAddressingWrite<_SP, &z80::op_push_auto>;         //
/*PUSH qq          */ op[0xF5]                                                                     = &z80::indirectAddressingWrite<_SP, &z80::op_push_manual<_AF> >;         //

/*PUSH IX          */ op[0xDDE5]                                                                   = &z80::indirectAddressingWrite<_SP, &z80::op_push_manual<_IX> >;         //
/*PUSH IY          */ op[0xFDE5]                                                                   = &z80::indirectAddressingWrite<_SP, &z80::op_push_manual<_IY> >;         //


/*RES b,r          */ op[0x87]=op[0x80]=op[0x81]=op[0x82]=op[0x83]=op[0x84]=op[0x85]               = &z80::implicitAddressing8<&z80::op_res_reg_auto>;         ////
/*RES b,r          */ op[0x8F]=op[0x88]=op[0x89]=op[0x8A]=op[0x8B]=op[0x8C]=op[0x8D]               = &z80::implicitAddressing8<&z80::op_res_reg_auto>;         ////
/*RES b,r          */ op[0x97]=op[0x90]=op[0x91]=op[0x92]=op[0x93]=op[0x94]=op[0x95]               = &z80::implicitAddressing8<&z80::op_res_reg_auto>;         ////
/*RES b,r          */ op[0x9F]=op[0x98]=op[0x99]=op[0x9A]=op[0x9B]=op[0x8C]=op[0x9D]               = &z80::implicitAddressing8<&z80::op_res_reg_auto>;         ////
/*RES b,r          */ op[0xA7]=op[0xA0]=op[0xA1]=op[0xA2]=op[0xA3]=op[0xA4]=op[0xA5]               = &z80::implicitAddressing8<&z80::op_res_reg_auto>;         ////
/*RES b,r          */ op[0xAF]=op[0xA8]=op[0xA9]=op[0xAA]=op[0xAB]=op[0xAC]=op[0xAD]               = &z80::implicitAddressing8<&z80::op_res_reg_auto>;         ////
/*RES b,r          */ op[0xB7]=op[0xB0]=op[0xB1]=op[0xB2]=op[0xB3]=op[0xB4]=op[0xB5]               = &z80::implicitAddressing8<&z80::op_res_reg_auto>;         ////
/*RES b,r          */ op[0xBF]=op[0xB8]=op[0xB9]=op[0xBA]=op[0xBB]=op[0xBC]=op[0xBD]               = &z80::implicitAddressing8<&z80::op_res_reg_auto>;         ////
/*RES b,(HL)	   */ op[0x86]=op[0x8E]=op[0x96]=op[0x9E]=op[0xA6]=op[0xAE]=op[0xB6]=op[0xBE]      = &z80::indirectAddressingRead<_HL, &z80::op_res_mem>;     /////
//DDCB and FDCB are done in uncocumented opcodes.


/*RET              */ op[0xC9]                                                                     = &z80::indirectAddressingWrite<_SP, &z80::op_ret<false> >;         //
/*RET cc           */ op[0xC0]=op[0xC8]=op[0xD0]=op[0xD8]=op[0xE0]=op[0xE8]=op[0xF0]=op[0xF8]      = &z80::indirectAddressingWrite<_SP, &z80::op_ret<true> >;         //
/*RETI             */ op[0xED4D]                                                                   = &z80::indirectAddressingWrite<_SP, &z80::op_reti >;         //
/*RETI             */ op[0xED45]                                                                   = &z80::indirectAddressingWrite<_SP, &z80::op_retn >;         //


/*RL  r            */ op[0xCB17]=op[0xCB10]=op[0xCB11]=op[0xCB12]=op[0xCB13]=op[0xCB14]=op[0xCB15] = &z80::implicitAddressing8<&z80::op_rl>;         //
/*RL (HL)          */ op[0xCB16]                                                                   = &z80::indirectAddressingWrite<_HL, &z80::op_rl_mem<_HL> >;         //
//DDCB and FDCB are done in uncocumented opcodes.
/*RLA              */ op[0x17]                                                                     = &z80::implicitAddressing8<&z80::op_rl>;         //
/*RLCA             */ op[0x07]                                                                     = &z80::implicitAddressing8<&z80::op_rlc>;         //
/*RLC              */ op[0xCB07]=op[0xCB00]=op[0xCB01]=op[0xCB02]=op[0xCB03]=op[0xCB04]=op[0xCB05] = &z80::implicitAddressing8<&z80::op_rlc>;         //
//DDCB and FDCB are done in uncocumented opcodes.
/*RLD              */ op[0xED6F]                                                                   = &z80::indirectAddressingRead<_HL, &z80::op_rld>;         //


/*RR  r            */ op[0xCB1F]=op[0xCB18]=op[0xCB19]=op[0xCB1A]=op[0xCB1B]=op[0xCB1C]=op[0xCB1D] = &z80::implicitAddressing8<&z80::op_rr>;         //
/*RL (HL)          */ op[0xCB1E]                                                                   = &z80::indirectAddressingWrite<_HL, &z80::op_rr_mem<_HL> >;         //
//DDCB and FDCB are done in uncocumented opcodes.
/*RRA              */ op[0x1F]                                                                     = &z80::implicitAddressing8<&z80::op_rr>;         //
/*RRC              */ op[0xCB0F]=op[0xCB08]=op[0xCB09]=op[0xCB0A]=op[0xCB0B]=op[0xCB0C]=op[0xCB0D] = &z80::implicitAddressing8<&z80::op_rrc>;         //
/*RRCA             */ op[0x0F]                                                                     = &z80::implicitAddressing8<&z80::op_rrc>;         //









}
